#include <Address.h>
#include <AddressException.h>
#include <Exception.h>
#include <IP.h>
#include <IPException.h>
#include <Socket.h>
#include <SocketException.h>
#include <SocketTCP.h>
#include <SocketUDP.h>
#include <Stats.h>
#include <StatsException.h>
#include <TransferCount.h>
#include <TransferCountException.h>
#include <HTTP.h>
#include <HTTPMessage.h>
#include <HTTPMessageGet.h>
#include <HTTPMessagePost.h>
#include <HTTPMessageResponse.h>
#include <uptimecl.h>
#include <types.h>

//#include <sys/utsname.h>
#include <sys/types.h>
//#include <sys/sysctl.h>
#include <string.h>
//#include <sys/param.h>
//#include <sys/errno.h>
//#include <sys/time.h>
#include <iostream>

extern int errno;

int main(int argc, char *argv[])
{
    char uptimeHost[256];
    int uptimePort;
    char uptimeURL[512];
    char username[256];
    char pass[256];


	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	 
	wVersionRequested = MAKEWORD( 2, 2 );
	 
	err = WSAStartup( wVersionRequested, &wsaData );

    
    memset(uptimeHost, 0, sizeof(uptimeHost));
    memset(uptimeURL, 0, sizeof(uptimeURL));
    memset(username, 0, sizeof(username));
    memset(pass, 0, sizeof(pass));
    
    // Llegim el fitxer de configuracio
    char conffile[1024];
    memset(conffile, 0, sizeof(conffile));
    
    if (argc==1)
	sprintf(conffile, "uptime.conf");
    else
	sprintf(conffile, "%s", argv[1]);
    
    FILE *fd;
    fd=fopen(conffile, "r");
    
    if (fd==NULL)
    {
	printf("Cannot open config file %s\n", conffile);
	return -5;
    }
    
    char line[1024];
    char var[512];
    char value[512];
    char *p;
    while(!feof(fd))
    {
	memset(line, 0, sizeof(line));
	memset(var, 0, sizeof(var));
	memset(value, 0, sizeof(value));
	fgets(line, sizeof(line), fd);
	
	if (strlen(line)==0)
	    continue;

	p=strchr(line, '\n');
	*p=0;
	
	if (strlen(line)==0)
	    continue;
	
	if (line[0]=='#')
	    continue;
	
	p=strchr(line, '=');
	strncpy(value, p+1, 512);
	*p=0;
	strncpy(var, line, 512);
	
	
	if (strcmp(var, "server")==0)
	    strncpy(uptimeHost, value, sizeof(uptimeHost));
	else if (strcmp(var, "port")==0)
	    uptimePort=atoi(value);
	else if (strcmp(var, "path")==0)
	    strncpy(uptimeURL, value, sizeof(uptimeURL));
	else if (strcmp(var, "user")==0)
	    strncpy(username, value, sizeof(username));
	else if (strcmp(var, "pass")==0)
	    strncpy(pass, value, sizeof(pass));	
    }
    
    fclose(fd);
    

    
    
    // Obtenim uptime a partir de sysctl(3) o de /proc/uptime
    long uptimeSecs;

	LARGE_INTEGER pcFreq, pcCount;
	BOOL resOK;

	resOK=QueryPerformanceFrequency(&pcFreq);

	if (!resOK)
	{
		printf("Uptime information is not available\n");
		return -6;
	}

    resOK=QueryPerformanceCounter(&pcCount);
    
	if (!resOK)
	{
		printf("Uptime information is not available\n");
		return -6;
	}

	uptimeSecs=(long)(pcCount.QuadPart/pcFreq.QuadPart);


	// Obtencio de la informacio del sistema
	char nodename[MAX_COMPUTERNAME_LENGTH+1];
	char release[256];
	char version[256];
	char machine[256];
	unsigned long bsize=MAX_COMPUTERNAME_LENGTH+1;

	// nom de la maquina
	memset(nodename, 0, sizeof(nodename));
	resOK=GetComputerName(nodename, &bsize);

	if (!resOK)
	{
		printf("Computer name information is not available\n");
		return -7;
	}


	// versio del sistema operatiu
	OSVERSIONINFO osvi;
	memset(release, 0, sizeof(release));
	memset(&osvi, 0, sizeof(OSVERSIONINFO));
	osvi.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);

	resOK=GetVersionEx(&osvi);

	if (!resOK)
	{
		printf("Operating system version information is not available\n");
		return -7;
	}

	if (osvi.dwMajorVersion==4 && osvi.dwMinorVersion==0 && osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
		sprintf(release, "95");
	else if (osvi.dwMajorVersion==4 && osvi.dwMinorVersion==10)
		sprintf(release, "98");
	else if (osvi.dwMajorVersion==4 && osvi.dwMinorVersion==90)
		sprintf(release, "Me");
	else if (osvi.dwMajorVersion==3 && osvi.dwMinorVersion==51)
		sprintf(release, "NT 3.51");
	else if (osvi.dwMajorVersion==4 && osvi.dwMinorVersion==0 && osvi.dwPlatformId==VER_PLATFORM_WIN32_NT)
		sprintf(release, "98");
	else if (osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0)
		sprintf(release, "2000");
	else if (osvi.dwMajorVersion==5 && osvi.dwMinorVersion==1)
		sprintf(release, "XP");

	memset(version, 0, sizeof(version));
	sprintf(version, "Build %u %s", osvi.dwBuildNumber, osvi.szCSDVersion);
    
    // Construccio del missatge HTTP
    char cuptime[256];
    memset(cuptime, 0, sizeof(cuptime));
    sprintf(cuptime, "%d", uptimeSecs);


	// informacio del hardware
	SYSTEM_INFO sisinfo;
	memset(&sisinfo, 0, sizeof(SYSTEM_INFO));
	memset(machine, 0, sizeof(machine));

	GetSystemInfo(&sisinfo);

	if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL && sisinfo.wProcessorLevel==3)
		sprintf(machine, "i386");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL && sisinfo.wProcessorLevel==4)
		sprintf(machine, "i486");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL && sisinfo.wProcessorLevel==5)
		sprintf(machine, "i586");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL && sisinfo.wProcessorLevel==6)
		sprintf(machine, "i686");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_MIPS)
		sprintf(machine, "MIPS");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_ALPHA && sisinfo.wProcessorLevel==21064)
		sprintf(machine, "Alpha 21064");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_ALPHA && sisinfo.wProcessorLevel==21066)
		sprintf(machine, "Alpha 21066");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_ALPHA && sisinfo.wProcessorLevel==21164)
		sprintf(machine, "Alpha 21164");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_PPC && sisinfo.wProcessorLevel==1)
		sprintf(machine, "PPC 601");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_PPC && sisinfo.wProcessorLevel==3)
		sprintf(machine, "PPC 603");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_PPC && sisinfo.wProcessorLevel==4)
		sprintf(machine, "PPC 604");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_PPC && sisinfo.wProcessorLevel==6)
		sprintf(machine, "PPC 603+");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_PPC && sisinfo.wProcessorLevel==9)
		sprintf(machine, "PPC 604+");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_PPC && sisinfo.wProcessorLevel==20)
		sprintf(machine, "PPC 620");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64)
		sprintf(machine, "IA64");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA32_ON_WIN64)
		sprintf(machine, "IA32W64");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
		sprintf(machine, "AMD64");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL && sisinfo.dwProcessorType==PROCESSOR_INTEL_386)
		sprintf(machine, "i386");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL && sisinfo.dwProcessorType==PROCESSOR_INTEL_486)
		sprintf(machine, "i486");
	else if (sisinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL && sisinfo.dwProcessorType==PROCESSOR_INTEL_PENTIUM)
		sprintf(machine, "i586");
	else
		sprintf(machine, "Unknown");

    HTTPMessagePost httpMsg(uptimeURL, HTTP_VERSION_1_0);

	httpMsg.addHdr("Host", uptimeHost);
    
    httpMsg.addVar("uptime", cuptime);
	httpMsg.addVar("sysname", "Windows");
	httpMsg.addVar("nodename", nodename);
	httpMsg.addVar("release", release);
	httpMsg.addVar("version", version);
	httpMsg.addVar("machine", machine);
    httpMsg.addVar("username", username);
    httpMsg.addVar("pass", pass);
        
    HTTP *conHttp;
    try
    {
	IP ip(uptimeHost);

	/*cout << "uptimeHost = " << uptimeHost << endl;
	cout << "IP = " << ip.toString() << endl;*/

	Address addr(ip, uptimePort);
	conHttp=new HTTP(&addr);
	conHttp->connect();
    }
    catch (Exception e)
    {
	cout << e.getMsg() << endl;
	return -4;
    }
    
    conHttp->sendMessage(&httpMsg);
   
    HTTPMessageResponse httpResponse;    
    conHttp->recvMessage(&httpResponse);
    
    
    char bufContent[1024];
    memset(bufContent, 0, sizeof(bufContent));
    
    httpResponse.getData(bufContent, sizeof(bufContent));
    
    printf("%s\n", bufContent);
    
    delete conHttp;
	WSACleanup();
    
    return 0;
}
